package com.zonski.jbots.desktop.application;

import java.awt.Frame;
import java.awt.Component;
import java.awt.BorderLayout;
import java.awt.event.WindowListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowAdapter;

import com.zonski.jbots.desktop.client.PainterCanvas;
import com.zonski.jbots.desktop.client.RoomRenderer;
import com.zonski.jbots.desktop.client.DesktopDevice;
import com.zonski.jbots.engine.FileInputStreamFactory;
import com.zonski.jbots.desktop.engine.InputMindKeyListener;
import com.zonski.jbots.desktop.engine.EngineRunner;
import com.zonski.jbots.desktop.engine.MinimalInputMindKeyListener;
import com.zonski.jbots.desktop.game.JBotsRoomRendererFactory;
import com.zonski.jbots.desktop.game.JBotsPanel;

import com.zonski.jbots.engine.Engine;
import com.zonski.jbots.engine.RoomFactory;

import com.zonski.jbots.game.entity.InputMind;
import com.zonski.jbots.game.entity.BadBotMind;
import com.zonski.jbots.game.entity.MinimalInputMind;
import com.zonski.jbots.game.JBotsEntityFactory;
import com.zonski.jbots.game.JBotsGameController;
import com.zonski.jbots.game.JBotsConstants;
import com.zonski.jbots.game.room.AsciiRoomFactory;

// room renderer imports

public class JBots
{
    public static final void main(String[] args)
    {
        try
        {
            run();
            //return 0;
        }catch(Exception ex){
            ex.printStackTrace();
            //return 1;
        }
    }

    public static void run() throws Exception
    {
        Frame frame = new Frame("JBots");

        DesktopDevice device = new ApplicationDevice(new FileInputStreamFactory("/sounds/", "wav"));
        Engine engine = new Engine(new JBotsEntityFactory(device), device);

        RoomFactory roomFactory = new AsciiRoomFactory(
            new FileInputStreamFactory(
                "/data/levels/", "lvl"
            )
        );
        JBotsGameController controller = new JBotsGameController(engine, roomFactory);
        EngineRunner runner = new EngineRunner(controller, device);
        controller.setEngineRunner(runner);
        controller.setMaxLevel(7);
        PainterCanvas canvas = new PainterCanvas(controller);
        controller.setMode(JBotsGameController.LOADING);

        device.setCanvas(canvas);
        runner.setCanvas(canvas);
        createPlayer(engine, canvas, 0);
        createBot(engine, 1);
        createBot(engine, 2);
        createBot(engine, 3);

        //runner.setTicksPerUpdate(200);
        
        //canvas.setSize(room.getWidth(), room.getHeight());
        JBotsPanel panel = new JBotsPanel();
        canvas.setSize(240, 200);
        panel.addCentrePanel(canvas);

        frame.setLayout(new BorderLayout());
        frame.add(panel, BorderLayout.CENTER);
        frame.pack();
        frame.setResizable(false);
        frame.addWindowListener(new ApplicationCloser(runner));

        // give the images as much time as possible to load by doing
        // this last
        JBotsRoomRendererFactory roomRendererFactory;
        roomRendererFactory = new JBotsRoomRendererFactory(canvas);
        RoomRenderer roomRenderer = roomRendererFactory.createRoomRenderer();
        canvas.setRoomRenderer(roomRenderer);

        frame.setVisible(true);
        canvas.requestFocus();
        controller.setMode(JBotsGameController.DEMO);
    }

    private static void createPlayer(Engine engine, Component component, int id)
    {
        MinimalInputMind mind = new MinimalInputMind();
        MinimalInputMindKeyListener listener = new MinimalInputMindKeyListener(mind);
        engine.setMind(Engine.getPlayerMindName(id), mind);
        component.addKeyListener(listener);
    }

    private static void createBot(Engine engine, int id)
    {
        BadBotMind mind = new BadBotMind(JBotsConstants.BOMB_BOT);
        //TempRockMind mind = new TempRockMind();
        engine.setMind(Engine.getPlayerMindName(id), mind);
    }

    private static class ApplicationCloser extends WindowAdapter
    {
        private EngineRunner runner;
        public ApplicationCloser(EngineRunner runner)
        {
            this.runner = runner;
        }

        public void windowClosing(WindowEvent event)
        {
            runner.stop();
            event.getWindow().dispose();
            System.exit(0);
        }
    }
}
